#ifndef FILE_READER_HPP
#define FILE_READER_HPP

#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/filesystem/path.hpp>
#include "word_tree.h++"

struct Word {
	std::string full_word;
	std::string lemma;
	std::string category;
	size_t word_index;
	size_t offset;
	Word() : full_word(), lemma(), category(), word_index(0), offset(0) {}
/*	Word(std::string _full_word, std::string _lemma = "", 
			std::string _category = "")
		: full_word(_full_word), lemma(_lemma), category(_category),
		word_index	{}*/
};

class StupidFileReader {
public:
	/**
	 * read a space separated file.
	 * @param basepath the path where to find the file
	 * @param doc the document. document will be opened as basepath/doc.get_path()
	 * @param caller the caller or any other objec that must have a
	 * found_word(Handle&, Word&) method.
	 * @param handler the handler to pass to found_word. (FIXME : use boost::bind)
	 */

	template <typename Caller>
	void read_file(const boost::filesystem::path& basepath,
			UnserializedDocument& doc,
			Caller& caller) {

		std::string filepath = (basepath/doc.get_path()).string();
			
		std::ifstream input(filepath.c_str(), std::ios::binary);
		std::string word;
		size_t index = 0;
		size_t lastpos = 0;
		input >> std::skipws;
		while (input >> word) {
			Word info;
			info.lemma = info.full_word = word;
			info.word_index = index;
			info.offset = lastpos;
			caller.found_word(doc, info);
			
			lastpos = input.tellg();
			index++;
		}
	}
};


class TreeTaggerFileReader {
public:

	size_t tell(std::istream& input) {
		bool good = input.good();
		if (!good)
			return input.tellg();
		size_t temp = input.tellg();
		if (!input.good()) {
			input.clear(); // don't tease me, bro.
			return 0;
		}
		return temp;
	}

	template <typename Caller>
	void read_stream(std::istream& input,
			UnserializedDocument& doc,
			Caller& caller) {

		std::string line;
		size_t index = 0;
		size_t lastpos = 0;
		while (input.good()) {
			std::getline(input, line, '\n');
			if (line.empty())
				break;
			std::istringstream lineinput(line);
			Word info;

			std::getline(lineinput, info.full_word, '\t');
			std::getline(lineinput, info.category, '\t');
			std::getline(lineinput, info.lemma);

			if (info.lemma == "<unknown>")
				// lemma is unknown ..... but we use it anyway.
				info.lemma = info.full_word;

			info.word_index = index;
			info.offset = lastpos;
			caller.found_word(doc, info);
			index++;
			lastpos = tell(input);
		}
	}

	template <typename Caller>
	void read_file(const boost::filesystem::path& basepath,
			UnserializedDocument& doc,
			Caller& caller) {

		std::ifstream input((basepath/doc.get_path()).c_str(),
					std::ios::binary);
		read_stream(input, doc, caller);
	}
};


#endif
